package com.cencat.merchant.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cencat.common.response.ApiResponse;
import com.cencat.merchant.dto.RouteInvoiceCreateDTO;
import com.cencat.merchant.dto.RouteInvoiceQueryDTO;
import com.cencat.merchant.dto.RouteInvoiceUpdateDTO;
import com.cencat.merchant.entity.RouteInvoice;
import com.cencat.merchant.service.RouteInvoiceService;
import com.cencat.merchant.vo.RouteInvoiceVO;
import com.cencat.merchant.vo.RouteInvoiceStatisticsVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

/**
 * 路线发票管理控制器
 * 提供路线发票的增删改查、统计、导出等功能
 * 
 * @author cencat
 * @since 2024-01-01
 */
@RestController
@RequestMapping("/api/merchant/route-invoice")
@Tag(name = "路线发票管理", description = "路线发票管理相关接口")
@Slf4j
public class RouteInvoiceController {

    @Autowired
    private RouteInvoiceService routeInvoiceService;

    /**
     * 创建路线发票
     * 
     * @param createDTO 发票创建DTO
     * @return 创建结果
     */
    @PostMapping
    @Operation(summary = "创建路线发票", description = "创建新的路线发票记录")
    public ApiResponse<RouteInvoiceVO> createRouteInvoice(@Valid @RequestBody RouteInvoiceCreateDTO createDTO) {
        log.info("创建路线发票，参数：{}", createDTO);
        try {
            RouteInvoiceVO invoiceVO = routeInvoiceService.createRouteInvoice(createDTO);
            log.info("路线发票创建成功，ID：{}", invoiceVO.getId());
            return ApiResponse.success(invoiceVO);
        } catch (Exception e) {
            log.error("创建路线发票失败", e);
            return ApiResponse.error("创建路线发票失败：" + e.getMessage());
        }
    }

    /**
     * 更新路线发票信息
     * 
     * @param id 发票ID
     * @param updateDTO 发票更新DTO
     * @return 更新结果
     */
    @PutMapping("/{id}")
    @Operation(summary = "更新路线发票", description = "更新路线发票信息")
    public ApiResponse<RouteInvoiceVO> updateRouteInvoice(
            @Parameter(description = "发票ID") @PathVariable @NotNull @Min(1) Long id,
            @Valid @RequestBody RouteInvoiceUpdateDTO updateDTO) {
        log.info("更新路线发票，ID：{}，参数：{}", id, updateDTO);
        try {
            RouteInvoiceVO invoiceVO = routeInvoiceService.updateRouteInvoice(id, updateDTO);
            log.info("路线发票更新成功，ID：{}", id);
            return ApiResponse.success(invoiceVO);
        } catch (Exception e) {
            log.error("更新路线发票失败，ID：{}", id, e);
            return ApiResponse.error("更新路线发票失败：" + e.getMessage());
        }
    }

    /**
     * 删除路线发票
     * 
     * @param id 发票ID
     * @return 删除结果
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除路线发票", description = "删除指定路线发票")
    public ApiResponse<Void> deleteRouteInvoice(
            @Parameter(description = "发票ID") @PathVariable @NotNull @Min(1) Long id) {
        log.info("删除路线发票，ID：{}", id);
        try {
            routeInvoiceService.deleteRouteInvoice(id);
            log.info("路线发票删除成功，ID：{}", id);
            return ApiResponse.success();
        } catch (Exception e) {
            log.error("删除路线发票失败，ID：{}", id, e);
            return ApiResponse.error("删除路线发票失败：" + e.getMessage());
        }
    }

    /**
     * 根据ID查询路线发票详情
     * 
     * @param id 发票ID
     * @return 发票详情
     */
    @GetMapping("/{id}")
    @Operation(summary = "查询路线发票详情", description = "根据ID查询路线发票详细信息")
    public ApiResponse<RouteInvoiceVO> getRouteInvoiceById(
            @Parameter(description = "发票ID") @PathVariable @NotNull @Min(1) Long id) {
        log.info("查询路线发票详情，ID：{}", id);
        try {
            RouteInvoiceVO invoiceVO = routeInvoiceService.getRouteInvoiceById(id);
            return ApiResponse.success(invoiceVO);
        } catch (Exception e) {
            log.error("查询路线发票详情失败，ID：{}", id, e);
            return ApiResponse.error("查询路线发票详情失败：" + e.getMessage());
        }
    }

    /**
     * 分页查询路线发票列表
     * 
     * @param queryDTO 查询条件
     * @return 发票分页列表
     */
    @GetMapping("/page")
    @Operation(summary = "分页查询路线发票", description = "根据条件分页查询路线发票列表")
    public ApiResponse<IPage<RouteInvoiceVO>> getRouteInvoicesByPage(@Valid RouteInvoiceQueryDTO queryDTO) {
        log.info("分页查询路线发票，参数：{}", queryDTO);
        try {
            IPage<RouteInvoiceVO> pageResult = routeInvoiceService.getRouteInvoicesByPage(queryDTO);
            return ApiResponse.success(pageResult);
        } catch (Exception e) {
            log.error("分页查询路线发票失败", e);
            return ApiResponse.error("查询路线发票列表失败：" + e.getMessage());
        }
    }

    /**
     * 根据路线ID查询发票
     * 
     * @param routeId 路线ID
     * @return 发票列表
     */
    @GetMapping("/route/{routeId}")
    @Operation(summary = "查询路线发票", description = "根据路线ID查询相关发票")
    public ApiResponse<List<RouteInvoiceVO>> getInvoicesByRouteId(
            @Parameter(description = "路线ID") @PathVariable @NotNull @Min(1) Long routeId) {
        log.info("查询路线发票，路线ID：{}", routeId);
        try {
            List<RouteInvoiceVO> invoices = routeInvoiceService.getInvoicesByRouteId(routeId);
            return ApiResponse.success(invoices);
        } catch (Exception e) {
            log.error("查询路线发票失败，路线ID：{}", routeId, e);
            return ApiResponse.error("查询路线发票失败：" + e.getMessage());
        }
    }

    /**
     * 根据日期范围查询发票
     * 
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 发票列表
     */
    @GetMapping("/date-range")
    @Operation(summary = "按日期查询发票", description = "根据日期范围查询路线发票")
    public ApiResponse<List<RouteInvoiceVO>> getInvoicesByDateRange(
            @Parameter(description = "开始日期") @RequestParam LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam LocalDate endDate) {
        log.info("按日期范围查询发票，开始日期：{}，结束日期：{}", startDate, endDate);
        try {
            List<RouteInvoiceVO> invoices = routeInvoiceService.getInvoicesByDateRange(startDate, endDate);
            return ApiResponse.success(invoices);
        } catch (Exception e) {
            log.error("按日期范围查询发票失败", e);
            return ApiResponse.error("查询发票失败：" + e.getMessage());
        }
    }

    /**
     * 审核发票
     * 
     * @param id 发票ID
     * @param approved 是否通过审核
     * @param auditRemark 审核备注
     * @return 审核结果
     */
    @PutMapping("/{id}/audit")
    @Operation(summary = "审核发票", description = "审核路线发票")
    public ApiResponse<Void> auditInvoice(
            @Parameter(description = "发票ID") @PathVariable @NotNull @Min(1) Long id,
            @Parameter(description = "是否通过审核") @RequestParam Boolean approved,
            @Parameter(description = "审核备注") @RequestParam(required = false) String auditRemark) {
        log.info("审核发票，ID：{}，审核结果：{}，备注：{}", id, approved, auditRemark);
        try {
            routeInvoiceService.auditInvoice(id, approved, auditRemark);
            log.info("发票审核成功，ID：{}", id);
            return ApiResponse.success();
        } catch (Exception e) {
            log.error("审核发票失败，ID：{}", id, e);
            return ApiResponse.error("审核发票失败：" + e.getMessage());
        }
    }

    /**
     * 支付发票
     * 
     * @param id 发票ID
     * @return 支付结果
     */
    @PutMapping("/{id}/pay")
    @Operation(summary = "支付发票", description = "标记发票为已支付")
    public ApiResponse<Void> payInvoice(
            @Parameter(description = "发票ID") @PathVariable @NotNull @Min(1) Long id) {
        log.info("支付发票，ID：{}", id);
        try {
            routeInvoiceService.payInvoice(id);
            log.info("发票支付成功，ID：{}", id);
            return ApiResponse.success();
        } catch (Exception e) {
            log.error("支付发票失败，ID：{}", id, e);
            return ApiResponse.error("支付发票失败：" + e.getMessage());
        }
    }

    /**
     * 获取发票统计信息
     * 
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 统计信息
     */
    @GetMapping("/statistics")
    @Operation(summary = "发票统计", description = "获取路线发票统计信息")
    public ApiResponse<RouteInvoiceStatisticsVO> getInvoiceStatistics(
            @Parameter(description = "开始日期") @RequestParam(required = false) LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) LocalDate endDate) {
        log.info("获取发票统计信息，开始日期：{}，结束日期：{}", startDate, endDate);
        try {
            RouteInvoiceStatisticsVO statistics = routeInvoiceService.getInvoiceStatistics(startDate, endDate);
            return ApiResponse.success(statistics);
        } catch (Exception e) {
            log.error("获取发票统计信息失败", e);
            return ApiResponse.error("获取统计信息失败：" + e.getMessage());
        }
    }

    /**
     * 导出发票数据
     * 
     * @param queryDTO 查询条件
     * @return 导出文件
     */
    @PostMapping("/export")
    @Operation(summary = "导出发票", description = "导出路线发票数据到Excel")
    public ResponseEntity<byte[]> exportInvoices(@Valid @RequestBody RouteInvoiceQueryDTO queryDTO) {
        log.info("导出发票数据，参数：{}", queryDTO);
        try {
            byte[] excelData = routeInvoiceService.exportInvoices(queryDTO);
            
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", "route_invoices.xlsx");
            
            log.info("发票数据导出成功");
            return ResponseEntity.ok().headers(headers).body(excelData);
        } catch (Exception e) {
            log.error("导出发票数据失败", e);
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 批量删除发票
     * 
     * @param ids 发票ID列表
     * @return 删除结果
     */
    @DeleteMapping("/batch")
    @Operation(summary = "批量删除发票", description = "批量删除指定的路线发票")
    public ApiResponse<Void> batchDeleteInvoices(@RequestBody List<Long> ids) {
        log.info("批量删除发票，IDs：{}", ids);
        try {
            routeInvoiceService.batchDeleteInvoices(ids);
            log.info("批量删除发票成功，数量：{}", ids.size());
            return ApiResponse.success();
        } catch (Exception e) {
            log.error("批量删除发票失败", e);
            return ApiResponse.error("批量删除发票失败：" + e.getMessage());
        }
    }

    /**
     * 批量审核发票
     * 
     * @param ids 发票ID列表
     * @param approved 是否通过审核
     * @param auditRemark 审核备注
     * @return 审核结果
     */
    @PutMapping("/batch/audit")
    @Operation(summary = "批量审核发票", description = "批量审核路线发票")
    public ApiResponse<Void> batchAuditInvoices(
            @RequestBody List<Long> ids,
            @Parameter(description = "是否通过审核") @RequestParam Boolean approved,
            @Parameter(description = "审核备注") @RequestParam(required = false) String auditRemark) {
        log.info("批量审核发票，IDs：{}，审核结果：{}，备注：{}", ids, approved, auditRemark);
        try {
            routeInvoiceService.batchAuditInvoices(ids, approved, auditRemark);
            log.info("批量审核发票成功，数量：{}", ids.size());
            return ApiResponse.success();
        } catch (Exception e) {
            log.error("批量审核发票失败", e);
            return ApiResponse.error("批量审核发票失败：" + e.getMessage());
        }
    }
}